package com.itheima.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.behaviour.dto.FollowBehaviourDto;
import com.itheima.common.constants.BusinessConstants;
import com.itheima.common.constants.SystemConstants;
import com.itheima.common.enums.HttpCodeEnum;
import com.itheima.common.exception.LeadNewsException;
import com.itheima.common.util.AppJwtUtil;
import com.itheima.common.util.RequestContextUtil;
import com.itheima.user.dto.LoginDto;
import com.itheima.user.dto.UserRelationDto;
import com.itheima.user.mapper.ApUserFanMapper;
import com.itheima.user.mapper.ApUserFollowMapper;
import com.itheima.user.mapper.ApUserMapper;
import com.itheima.user.pojo.ApUser;
import com.itheima.user.pojo.ApUserFan;
import com.itheima.user.pojo.ApUserFollow;
import com.itheima.user.service.ApUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

/**
 * @description <p>APP用户信息 业务实现</p>
 *
 * @version 1.0
 * @package com.itheima.user.service.impl
 */
@Service
public class ApUserServiceImpl extends ServiceImpl<ApUserMapper, ApUser> implements ApUserService {

    @Autowired
    private ApUserFollowMapper apUserFollowMapper;

    @Autowired
    private ApUserFanMapper apUserFanMapper;

    @Autowired
    private KafkaTemplate kafkaTemplate;
    /**
     * 登录校验
     *
     * @param loginDto
     * @return
     */
    @Override
    public Map<String, Object> loginCheck(LoginDto loginDto) {
        if(null == loginDto){
            //抛异常，缺少参数
            throw new LeadNewsException(HttpCodeEnum.PARAM_REQUIRE);
        }
        //手机号码
        String phone = loginDto.getPhone();
        //密码
        String password = loginDto.getPassword();
        //创建map集合封装数据
        Map<String, Object> resultMap = new HashMap<>();
        Long loginUserId = 0l;
        Map<String, Object> map = new HashMap<>();
        //判断是否是匿名登录
        if(StringUtils.isEmpty(phone) && StringUtils.isEmpty(password)){
            //如果是匿名，id为0--生成固定的token
            String token = AppJwtUtil.createToken(SystemConstants.ANONYMOUS_USER_ID);
            resultMap.put("token",token);
        }else {
            //查询用户
            ApUser loginUser = query().eq("phone", phone).one();
            if(null == loginUser){
                throw new LeadNewsException("用户名或密码不正确");
            }
            //密码加盐
            password += loginUser.getSalt();
            String digestAsHex = DigestUtils.md5DigestAsHex(password.getBytes());
            //校验
            if(!digestAsHex.equals(loginUser.getPassword())){
                throw new LeadNewsException("用户名或密码不正确");
            }
            loginUserId = loginUser.getId();
            loginUser.setPassword("");
            loginUser.setSalt("");
            resultMap.put("user", JSON.toJSONString(loginUser));
            map.put(SystemConstants.LOGIN_USER_IMAGE,loginUser.getImage());
            map.put(SystemConstants.LOGIN_USER_NAME,loginUser.getName());
        }
        //校验通过后，生成token，返回user信息
        map.put("id",loginUserId);
        //创建token
        String token = AppJwtUtil.createToken(map);
        resultMap.put("token",token);
        return resultMap;
    }

    /**
     * 关注与取消关注
     *
     * @param dto
     */
    @Override
    @Transactional
    public void userFollow(UserRelationDto dto) {
        //参数校验
        if(null == dto){
            throw new LeadNewsException(HttpCodeEnum.PARAM_INVALID);
        }
        //判断当前用户是否为匿名用户
        if(RequestContextUtil.isAnonymous()){
            throw new LeadNewsException(HttpCodeEnum.NEED_LOGIN);
        }
        //获取作者id
        Long authorId = dto.getAuthorId();
        //获取用户id
        Long loginUserId = Long.parseLong(RequestContextUtil.getUserId());

        //操作的类型
        Integer operation = dto.getOperation();

        //判断操作类型
        //为了留住痕迹，取消关注不删除记录
        if(operation == 0){
            //取消关注-删除关注记录
            removeFollow(loginUserId,authorId);
            //删除粉丝记录
            removeFans(authorId,loginUserId);
        }else {
            //添加关注和粉丝记录
            //需要判断是否关注过
            LambdaQueryWrapper<ApUserFollow> lqw = new LambdaQueryWrapper<>();
            lqw.eq(ApUserFollow::getUserId, loginUserId);
            lqw.eq(ApUserFollow::getFollowId, authorId);
            ApUserFollow apUserFollow = apUserFollowMapper.selectOne(lqw);
            if (null != apUserFollow) {
                //关注过了
                throw new LeadNewsException("已经关注过了");
            }

            //没关注过-查询用户信息和作者信息，将信息添加
            ApUser apUser = getById(loginUserId);
            ApUser author = getById(authorId);
            //添加关注
            addFollow(loginUserId, author);
            addFans(authorId, apUser);

            //构建用户行为dto
            FollowBehaviourDto behaviourDto = new FollowBehaviourDto();

            behaviourDto.setFollowId(authorId);
            behaviourDto.setArticleId(dto.getArticleId());
            behaviourDto.setUserId(loginUserId);
            kafkaTemplate.send(BusinessConstants.MqConstants.FOLLOW_BEHAVIOR_TOPIC,
                    JSON.toJSONString(behaviourDto));

        }
    }

    /**
     * 删除粉丝记录
     * @param authorId
     * @param loginUserId
     */
    private void removeFans(Long authorId, Long loginUserId) {
        LambdaQueryWrapper<ApUserFan> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ApUserFan::getUserId,loginUserId);
        lqw.eq(ApUserFan::getFansId,authorId);
        apUserFanMapper.delete(lqw);
    }

    /**
     * 删除关注记录
     * @param loginUserId
     * @param authorId
     */
    private void removeFollow(Long loginUserId, Long authorId) {
        LambdaQueryWrapper<ApUserFollow> lqw = new LambdaQueryWrapper<>();
        lqw.eq(ApUserFollow::getUserId,loginUserId);
        lqw.eq(ApUserFollow::getFollowId,authorId);
        apUserFollowMapper.delete(lqw);
    }

    /**
     * 添加关注
     * @param loginUserId
     * @param author
     */
    private void addFollow(Long loginUserId, ApUser author) {
        ApUserFollow follow = new ApUserFollow();
        follow.setUserId(loginUserId);
        follow.setFollowId(author.getId());
        follow.setFollowName(author.getName());
        follow.setLevel(1);//一般
        follow.setIsNotice(1);//要通知
        follow.setCreatedTime(LocalDateTime.now());
        apUserFollowMapper.insert(follow);
    }

    /**
     * 添加粉丝
     * @param authorId
     * @param apUser
     */
    private void addFans(Long authorId, ApUser apUser) {
        ApUserFan apUserFan = new ApUserFan();

        apUserFan.setUserId(authorId);
        apUserFan.setFansId(apUser.getId());
        apUserFan.setFansName(apUser.getName());
        apUserFan.setLevel(0);
        apUserFan.setCreatedTime(LocalDateTime.now());
        apUserFan.setIsDisplay(1);
        apUserFan.setIsShieldLetter(0);
        apUserFan.setIsShieldComment(0);
        apUserFanMapper.insert(apUserFan);

    }
}
